package com.beantools.reflect.enums;

import com.alibaba.fastjson.JSONObject;
import com.beantools.execption.ClassException;
import com.beantools.execption.PropertyException;
import com.beantools.util.ArrayUtil;

import java.util.LinkedList;
import java.util.List;

import static com.beantools.reflect.enums.EnumObjectJson.objToJson;
import static com.beantools.util.ArrayUtil.isEmpty;
import static com.beantools.util.ClassUtil.getClassNameByClass;
import static com.beantools.util.ObjectUtil.isNull;

/**
 * 这是将enum类转化为json对象的类，同时，调用者可以指定当前枚举类可以
 * 加载出哪些属性。前提是，枚举的<code>name值</code>已经过滤掉，同时，
 * 也过滤掉了<code>$VALUES</code>,因而，用户所指定的枚举的属性时私有属性
 *
 * @author baoya
 * @version 1.1.0
 * @since 1.1.0
 */

public class EnumClassJson extends AbstractsEnumJson {


    /**
     * 这是将枚举类字面常量转化为json对象并指定哪些属性可以被加载出来，同时以枚举类对象作为key值加载到
     * <code>JSONObject</code>中。
     * <p>
     * 如果<code>clazz</code>为空，则返回<code>null</code>
     * <p>
     * 如果<code>fieldNames</code>为null，或者长度为0，则返回当前包下的所有
     * <strong>private</strong>属性信息
     *
     * @param clazz      类字面常量
     * @param fieldNames 调用者指定的属性
     * @return 装载有key值的JSONObject对象
     */
    public static JSONObject assignPropertyJson(Class clazz, String... fieldNames) throws ClassException, PropertyException {
        try {
            if (isNull(clazz)) {
                return null;
            }
            List<JSONObject> jsonObjects = assignPropertyJsons(clazz, fieldNames);
            JSONObject body = new JSONObject(jsonObjects.size());
            body.put(getClassNameByClass(clazz), jsonObjects.size() <= 0 ? null : jsonObjects);
            return body;
        } catch (ClassException e) {
            throw new ClassException(e.getMessage());
        }
    }

    /**
     * 这是将枚举类字面常量转化为json对象并指定哪些属性可以被加载出来。
     * <p>
     * 如果<code>clazz</code>为空，则返回<code>null</code>
     * <p>
     * 如果<code>fieldNames</code>为null，或者长度为0，则返回当前包下的所有
     * <strong>private</strong>属性信息
     *
     * @param clazz      类字面常量
     * @param fieldNames 调用者指定的属性
     * @return 当前枚举类对象的集合
     */
    public static List<JSONObject> assignPropertyJsons(Class clazz, String... fieldNames) throws ClassException, PropertyException {
        try {
            List<JSONObject> var = listJsons(clazz);
            if (isEmpty(fieldNames)) {
                return var;
            }
            for (JSONObject jsonObject : var) {
                checkRemoveKey(jsonObject, fieldNames, clazz);
            }
            return var;
        } catch (ClassException e) {
            throw new ClassException(e.getMessage());
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (PropertyException e) {
            throw new PropertyException(e.getMessage());
        }
        return null;
    }


    /**
     * 这是将枚举类字面常量转化为json对象并指定哪些属性可以被加载出来。
     * <p>
     * 如果<code>clazz</code>为空，则返回<code>null</code>
     *
     * @param clazz 类字面常量
     * @return 当前枚举类的JSONObject的对象
     */
    public static JSONObject getJsonObject(Class clazz) throws ClassException {
        try {
            if (isNull(clazz)) {
                return null;
            }
            List<JSONObject> jsonObjects = listJsons(clazz);
            JSONObject body = new JSONObject(jsonObjects.size());
            body.put(getClassNameByClass(clazz), jsonObjects.size() <= 0 ? null : jsonObjects);
            return body;
        } catch (ClassException e) {
            throw new ClassException(e.getMessage());
        }
    }

    /**
     * 这是将枚举类字面常量转化为json对象并指定哪些属性可以被加载出来。
     * <p>
     * 如果<code>clazz</code>为空，则返回<code>null</code>
     *
     * @param clazz 类字面常量
     * @return 当前枚举类的JSONObject的容器对象
     */
    public static List<JSONObject> listJsons(Class clazz) throws ClassException {
        if (isNull(clazz)) {
            return null;
        }
        if (!clazz.isEnum()) {
            throw new ClassException(clazz.getSimpleName() + "不是枚举类", clazz);
        }
        List<JSONObject> list = new LinkedList<>();
        Object[] enumConstants = clazz.getEnumConstants();
        if (ArrayUtil.isEmpty(enumConstants)) {
            return null;
        }
        for (Object enumConstant : enumConstants) {
            list.add(objToJson(enumConstant));
        }
        return list;
    }


}
